<template>
  <div ref="graphContainer" class="graph-wrap">
    <div v-if="graphData?.nodes?.length" class="graph-container"></div>
    <noData v-else></noData>
  </div>
</template>

<script lang="ts" setup>
import { defineProps, ref, onMounted, reactive, PropType } from 'vue';
import G6 from '@antv/g6';
import { useStore } from 'vuex';
const store = useStore();
const props = defineProps({
  rowList: {
    type: Object as PropType<any>,
    default: () => {
      return {};
    },
  },
});
const graph = ref<any | null>(null);
const graphContainer = ref<any | null>(null);
let graphData = reactive<any | null>({
  edges: [],
  nodes: [],
});
const searchContent = reactive<any | null>({
  keyword: '',
  vertexLabel: '',
  pageNumber: 1,
  pageSize: 100,
});
onMounted(async () => {
  searchContent.keyword = props.rowList.assetId;
  searchContent.vertexLabel = props.rowList.assetType;
  await getGraphData();
  initG6();
});
const initG6 = () => {
  // 获取图容器的 DOM 元素
  const graphContainers = graphContainer.value;
  const width = graphContainers.clientWidth;
  const height = graphContainers.clientHeight || 500;
  const graphs: any = new G6.Graph({
    container: graphContainers,
    width,
    height,
    layout: {
      type: 'force',
      preventOverlap: true,
      linkDistance: (d) => {
        if (d.source.level === 1) {
          return 200;
        }
        return 100;
      },
      nodeStrength: (d) => {
        if (d.level === 2 || d.level === 3) {
          return -500;
        }
        return -100;
      },
      edgeStrength: (d) => {
        if (d.source.level === 1) {
          return 0.8;
        }
        if (d.source.level === 2) {
          return 0.4;
        }
        return 0.2;
      },
    },
    defaultNode: {
      // color: '#ffffff',
      // type: 'Attack-node',
    },
    defaultEdge: {
      type: 'line',
      style: {
        opacity: 1,
        stroke: '#516C83',
        lineWidth: 1,
        endArrow: {
          fill: '#516C83',
          path: G6.Arrow.triangle(5, 20, 25),
          d: 25,
        },
      },
      labelCfg: {
        autoRotate: true,
        refY: 0,
        style: {
          // stroke: '#FAFAFC',
          fill: '#9CA2B0',
          fontSize: 10,
          // lineWidth: 10,
          opacity: 1,
        },
      },
    },
    edgeStateStyles: {
      hover: {
        endArrow: {
          fill: '#2B8AFF',
          path: G6.Arrow.triangle(5, 5, 25),
          d: 20,
        },
        opacity: 1,
        lineWidth: 2,
        stroke: '#2B8AFF',
      },
    },

    modes: {
      default: ['drag-canvas'],
    },
  });

  graph.value = graphs;

  const data = {
    nodes: [
      {
        id: 'node0',
        // size: 50,
        type: 'bg-gradients-node', // 这里的 type 应该与注册的节点名称匹配
        label: 'Custom Node 1',
        gradient: 'vertexGradient',
        shapeType: 'circle',
        icon: {
          text: '\uE90B',
          show: true,
        },
      },
      {
        id: 'node1',
        // size: 30,
        type: 'bg-gradients-node', // 这里的 type 应该与注册的节点名称匹配
        label: 'Custom Node 2',
        gradient: 'typeGradient',
        shapeType: 'circle',
        icon: {
          text: '\uE90B',
          show: true,
        },
      },
      {
        id: 'node2',
        // size: 30,
        type: 'bg-gradients-node', // 这里的 type 应该与注册的节点名称匹配
        label: 'Custom Node 3',
        gradient: 'subordinateGradient',
        shapeType: 'circle',
        icon: {
          text: '\uE90B',
          show: true,
        },
      },
      {
        id: 'node3',
        // size: 30,
        type: 'bg-gradients-node', // 这里的 type 应该与注册的节点名称匹配
        label: 'Custom Node 4',
        gradient: 'subordinateGradient',
        shapeType: 'circle',
        icon: {
          text: '\uE90B',
          show: true,
        },
      },
      { id: 'node4', size: 30, isLeaf: true },
      { id: 'node5', size: 30, isLeaf: true },
      { id: 'node6', size: 15, isLeaf: true },
      { id: 'node7', size: 15, isLeaf: true },
      { id: 'node8', size: 15, isLeaf: true },
      { id: 'node9', size: 15, isLeaf: true },
      { id: 'node10', size: 15, isLeaf: true },
      { id: 'node11', size: 15, isLeaf: true },
      { id: 'node12', size: 15, isLeaf: true },
      { id: 'node13', size: 15, isLeaf: true },
      { id: 'node14', size: 15, isLeaf: true },
      { id: 'node15', size: 15, isLeaf: true },
      { id: 'node16', size: 15, isLeaf: true },
    ],
    edges: [
      { source: 'node0', target: 'node1' },
      { source: 'node0', target: 'node2' },
      { source: 'node0', target: 'node3' },
      { source: 'node0', target: 'node4' },
      { source: 'node0', target: 'node5' },
      { source: 'node1', target: 'node6' },
      { source: 'node1', target: 'node7' },
      { source: 'node2', target: 'node8' },
      { source: 'node2', target: 'node9' },
      { source: 'node2', target: 'node10' },
      { source: 'node2', target: 'node11' },
      { source: 'node2', target: 'node12' },
      { source: 'node2', target: 'node13' },
      { source: 'node3', target: 'node14' },
      { source: 'node3', target: 'node15' },
      { source: 'node3', target: 'node16' },
    ],
  };
  const nodes = data.nodes;
  graphs.data(graphData);
  graphs.render();

  graphs.on('node:dragstart', function (e) {
    graphs.layout();
    refreshDragedNodePosition(e);
  });
  graphs.on('node:drag', function (e) {
    refreshDragedNodePosition(e);
  });
  graphs.on('node:dragend', function (e) {
    e.item.get('model').fx = null;
    e.item.get('model').fy = null;
  });

  if (typeof window !== 'undefined') {
    window.onresize = () => {
      if (!graphs || graphs.get('destroyed')) return;
      if (
        !graphContainers ||
        !graphContainers.scrollWidth ||
        !graphContainers.scrollHeight
      )
        return;
      graphs.changeSize(
        graphContainers.scrollWidth,
        graphContainers.scrollHeight,
      );
    };
  }

  function refreshDragedNodePosition(e) {
    const model = e.item.get('model');
    model.fx = e.x;
    model.fy = e.y;
  }

  // 解决g6debug
  graphs.get('canvas').set('localRefresh', false);
};

const getGraphData = async () => {
  const { code, data } = await store.dispatch(
    'attack/getRelationships',
    searchContent,
  );
  if (code === 0) {
    if (!data) {
      graphData = {
        edges: [],
        nodes: [],
      };
      return;
    }

    data.edges =
      data.edges?.map((el) => {
        return {
          ...el,
        };
      }) || [];

    data.nodes =
      data.nodes?.map((el) => {
        let gradient = 'vertexGradient';
        let icon = {
          text: '\uE90B',
          show: true,
        };
        if (el.level === 1) {
          // 顶级
          gradient = 'vertexGradient';
        } else if (el.level === 2) {
          gradient = 'typeGradient';
        } else if (el.level === 3) {
          gradient = 'subordinateGradient';
        }

        return {
          ...el,
          type: 'bg-gradients-node', // 这里的 type 应该与注册的节点名称匹配
          gradient: gradient,
          shapeType: 'circle',
          icon,
        };
      }) || [];

    graphData = data;
  }
};
const waitForGraphContainer = () => {
  return new Promise<void>((resolve) => {
    const interval = setInterval(() => {
      if (graphContainer.value) {
        clearInterval(interval);
        resolve();
      }
    }, 100);
  });
};
</script>

<style lang="scss" scoped>
.graph-wrap {
  width: 100%;
  height: 100%;
}
</style>
